using System;
using System.IO;

namespace TKH.Biztalk.Diagnostics
{
    /// <summary>
    /// 
    /// </summary>
    public class XmlTraceListener : System.Diagnostics.XmlWriterTraceListener
    {
        string _originalFilename = string.Empty;
        string _currentFilename = string.Empty;
        object _lock = new object();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        public XmlTraceListener(string filename) : base(filename) { StartTraceListener(filename); }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="name"></param>
        public XmlTraceListener(string filename, string name) : base(filename, name) { StartTraceListener(filename); }

        /// <summary>
        /// Starts the trace listener.
        /// </summary>
        /// <param name="filename">The filename.</param>
        private void StartTraceListener(string filename)
        {
            _originalFilename = filename;
            CreateNewFile();
            StartMethod(filename);
        }

        /// <summary>
        /// The initial file that is created can be deleted as it does not contain any trace information
        /// </summary>
        /// <param name="filename">The filename.</param>
        public void StartMethod(string filename)
        {
            lock (_lock)
            {
                try
                {
                    File.Delete(filename);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.TraceError("Failed to delete initial file of TraceListener: " + ex.Message);
                }
            }
        }

        /// <summary>
        /// Checks the file constraints to see if a new file should be created
        /// </summary>
        private void CheckFileConstraints()
        {
            lock (_lock)
            {
                FileInfo info = new FileInfo(_currentFilename);
                TimeSpan ts = DateTime.Now.Subtract(info.CreationTime);

                if (ts.Minutes > XmlTraceListenerConfiguration.Current.MaxDurationMinutes ||
                    info.Length > XmlTraceListenerConfiguration.Current.MaxFileSizeBytes)
                {
                    CreateNewFile();
                }
            }
        }

        /// <summary>
        /// Creates the new file.
        /// </summary>
        private void CreateNewFile()
        {
            lock (_lock)
            {
                this.Flush();

                if (this.Writer != null)
                {
                    this.Writer.Flush();
                    this.Writer.Close();
                }

                //Create new file name
                string location = Path.GetDirectoryName(_originalFilename);

                if (Path.HasExtension(_originalFilename))
                {
                    _currentFilename = Path.Combine(location, string.Format("{0}-{1}{2}", DateTime.Now.ToString("yyyyMMdd-HHmmss"), Path.GetFileNameWithoutExtension(_originalFilename), Path.GetExtension(_originalFilename)));
                }
                else
                {
                    _currentFilename = Path.Combine(location, string.Format("{0}-{1}.svclog", DateTime.Now.ToString("yyyyMMdd-HHmmss"), Path.GetFileNameWithoutExtension(_originalFilename)));
                }

                this.Writer = File.CreateText(_currentFilename);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventCache"></param>
        /// <param name="source"></param>
        /// <param name="eventType"></param>
        /// <param name="id"></param>
        /// <param name="data"></param>
        public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object data)
        {
            CheckFileConstraints();
            if (data is BiztalkEvent)
            {
                data = ((BiztalkEvent)data).CreateNavigator();
            }
            base.TraceData(eventCache, source, eventType, id, data);

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventCache"></param>
        /// <param name="source"></param>
        /// <param name="eventType"></param>
        /// <param name="id"></param>
        /// <param name="data"></param>
        public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, params object[] data)
        {
            CheckFileConstraints();
            object[] data2 = new object[data.Length];
            for (int i = 0; i < data.Length; i++)
            {
                data2[i] = data[i] is BiztalkEvent ? ((BiztalkEvent)data[i]).CreateNavigator() : data[i];
            }
            base.TraceData(eventCache, source, eventType, id, data2);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventCache"></param>
        /// <param name="source"></param>
        /// <param name="eventType"></param>
        /// <param name="id"></param>
        public override void TraceEvent(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id)
        {
           
            base.TraceEvent(eventCache, source, eventType, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventCache"></param>
        /// <param name="source"></param>
        /// <param name="eventType"></param>
        /// <param name="id"></param>
        /// <param name="format"></param>
        /// <param name="args"></param>
        public override void TraceEvent(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string format, params object[] args)
        {
            CheckFileConstraints();
            base.TraceEvent(eventCache, source, eventType, id, format, args);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventCache"></param>
        /// <param name="source"></param>
        /// <param name="eventType"></param>
        /// <param name="id"></param>
        /// <param name="message"></param>
        public override void TraceEvent(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string message)
        {
            CheckFileConstraints();
            base.TraceEvent(eventCache, source, eventType, id, message);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventCache"></param>
        /// <param name="source"></param>
        /// <param name="id"></param>
        /// <param name="message"></param>
        /// <param name="relatedActivityId"></param>
        public override void TraceTransfer(System.Diagnostics.TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
        {
            CheckFileConstraints();
            base.TraceTransfer(eventCache, source, id, message, relatedActivityId);
        }
    }
}
